/**
 *@fileOverview This script aids in the creation and maintenance of cues within
 *an After Effects file. These cues can then be exported with in and out point
 *timecodes as well as imported from CSV. All cues are created within the main
 *composition that the user chooses within the UI
 *
 *@author Collin Brooks collin.brooks@gmail.com
 *@version 1
 */

//TODO:
//VALIDATE IMPORT
//MOVE FORWARD AND BACK FRAMES FROM UI
//ENTER TIME FOR CUE TO BE CREATED
//ATTACH USER FORMAT AND SEPARATOR TO THE IMPORT FUNCTION


COB = undefined;

/**
 *This script utilizes and extends the COB object. If the COB object is not
 *defined, define it.
 */
if (COB === undefined)
{
	//Import the COB include
    $.evalFile(new File(new File($.fileName).path + "/COB_v1.jsxinc"));
}

/******************************************************************\
>>>>>>> SCRIPT PROPERTIES
\******************************************************************/

//Create Script global object (CH = Layer Info)

/**
 *@class The main CK (Cue Keeper) class.
 *This class includes all of the required classes, methods and fields required
 *to use the CK script. It servese as this script's global environment.
 *
 *@extends #COB
 *@constructor
 */
COB.CK = {};

/**
 *The name of this script
 *@type String
 */
COB.CK.scriptName = "COB Cue Keeper";
/**
 *The version of this script
 *@type String
 */
COB.CK.scriptVersion = ".5";
/**
 *The description of this script
 *@type String
 */
COB.CK.scriptDescription = "Helps with the creation of cue in and out points " +
    "as well as generates a list of the in and out points within " +
    "a composition.";
/**
 *The file name of this script
 *@type String
 */
COB.CK.scriptFileName = "COB_Cue_Keeper.jsx";

/**
 *The current composition that is active
 *@type CompItem
 */
COB.CK.currentComp = {};
/**
 *An array of currently selected layers within the active composition
 *@type Array of LayerItems
 *@see #currentComp
 */
COB.CK.selectedLayers = {};

/******************************************************************\
>>>>>>> GLOBAL LANGUAGE STRINGS
\******************************************************************/

//Format types
COB.CK.formatTypes = {FRAMES: 'Frames', SECONDS: 'Seconds'};

//Marker in out language
COB.CK.markerName = {IN: "In", OUT: "Out"};

//The name of the null layer to place markers on.
COB.CK.markerLayerName = "Cue Keeper";

//Confirmation message for marker move
COB.CK.confirmMarkerMove = "This marker already exists. " +
    "Would you like to move it?";

/******************************************************************\
>>>>>>> REGEX
\******************************************************************/

COB.CK.regex = {};
COB.CK.regex.getCueNumber = /^\d*/;
COB.CK.regex.getCueType = new RegExp(
    COB.CK.markerName.IN + "|" + COB.CK.markerName.OUT + "$"
);

/******************************************************************\
>>>>>>> ERROR STRINGS
\******************************************************************/

COB.CK.errors = {
	UNKNOWN_FORMAT_TYPE: "An unknown format type was achieved from the UI",
	UNDEFINED_PROJECT: "You must have a project open in order to run " +
        "this script!",
	UNDEFINED_COMP: "You must have an active composition selected in order to" +
        " run this script",
	SECONDS_WITH_SEMI_COLON: "Because seconds values contain a semi-colon, " +
        "you cannot select 'Semi-Colon' as a separator. Please choose a " +
        "different separator.",
	MALFORMED_MARKERS: "The Cue Keeper Markers are malformed. This could " +
        "happen if the cues do not follow the logical " +
        COB.CK.markerName.IN + " and " + COB.CK.markerName.OUT + "order. " +
        "Please double check your markers to make sure each cue has both " +
        COB.CK.markerName.IN + " and " + COB.CK.markerName.OUT + " marker" +
        "types."
};

/******************************************************************\
>>>>>>> UI SETUP
\******************************************************************/
COB.CK.UI = (function (thisObj)
{
	//Variable declarations
    var res,
    s,

    //UI Shortcut Variables
    importExportRow1,
    importExportRow2,
    cueCreationPanelRow1,
    cueCreationPanelRow2,
    buttonRow,
    setupPanel,
    timeModPanel,

    //Function placeholders
    refreshCompList,
    moveTime,

	//Language Strings
	lang = {
		windowName: "COB - Layer In and Out Point Info",
		cueCreationPanelTitle: "Cue Creation",
		cueNumber: "Cue Number",
		plusButton: "+",
		minusButton: "-",
		timeModPanelTitle: "Time Modification",
		timeBackTen: "\u21E4",
		timeBackOne: "\u2190",
		timeForwardTen: "\u21E5",
		timeForwardOne: "\u2192",
        refreshButton: "\u21BB",
		importExportButtonShowText: "Show Import Export",
		importExportButtonHideText: "Hide Import Export",
		closeButton: "Close",
		importExportPanelTitle: "Import/Export",
		timeFormat: "Time Format",
		infoSeparator: "Info Separator",
		importButton: "Import",
		exportButton: "Export",
		tab: "Tab",
		comma: "Comma",
		semiColon: "Semi-Colon",
		newLine: "New Line"
	},
	
	
	//Separator Types
	separator = function (n, s) {
		var name = n,
            symbol = s;
		return {
			//Getters
			getName: function () {
				return name;
			},
			getSymbol: function () {
				return symbol;
			},
			//Setters
			setName: function (n) {
				name = n;
			},
			setSymbol: function (s) {
				symbol = s;
			}
		};
	},

	//The array of separators
	separators = [
		separator(lang.tab, "\t"),
		separator(lang.comma, ","),
		separator(lang.semiColon, ";"),
		separator(lang.newLine, "\n")
	],
	
	//Window/Panel setup
	myWindow = (thisObj instanceof Panel) ? thisObj : new Window(
        "palette",
        "COB - Layer In and Out Point Info",
        undefined,
        {resizeable: true}
    );
	
	//Add the resources for this window

//	try{
	res = "group { " +
        "orientation: 'column'," +
        "margins:0," +
        "alignment:['fill','fill']," +
        "setupRow: Group {" +
            "orientation: 'row'," +
            "margins: 5," +
            "alignment: ['fill', 'fill']," +
            "setupPanel: Panel {" +
                "text: 'Setup'," +
                "orientation: 'row'," +
                "margins: 5," +
                "alignment: ['fill', 'fill']," +
                COB.UI_helper.generateInputField({
                    "groupName": "mainCompGroup",
                    "labelName": "s",
                    "labelText": "Main Composition:",
                    "inputName": "e",
                    "inputMinSize": "[25,15]"
                    },
                    "DropDownList",
                    "refreshCompButton: Button {" +
                        "text: '" + lang.refreshButton + "'," +
                        "size:[20,15]," +
                        "alignment:['right','fill']" +
                    "}" //End refreshCompButton
                ) +
            "}," + //End setupPanel
        "}," + //End setupRow
        "row1: Group {" +
            "orientation: 'row'," +
            "margins: 5," +
            "alignment: ['fill', 'fill']," +
            "cueCreationPanel: Panel {" +
                "text: '" + lang.cueCreationPanelTitle + "'," +
                "margins: 15," +
                "alignment: ['fill','fill']," +
                "minimumSize: [180, 50]," +
                "orientation: 'column'," +
                "row1: Group {" +
                    "orientation: 'row'," +
                    "margins:0," +
                    "alignment: ['center','middle']," +
                    "minimumSize: [50, 15]," +
                    "preferredSize: [50, 15]," +
                    COB.UI_helper.generateInputField({
                        "groupName": "cue",
                        "labelName": "s",
                        "labelText": lang.cueNumber,
                        "inputName": "e",
                        "inputText": "1",
                        "inputMinSize": "[25,15"
                    }) +
                    "plusButton: Button {" +
                        "text: '" + lang.plusButton + "'," +
                        "preferredSize: [20, 15]" +
                    "}," + //End plusButton
                    "minusButton: Button {" +
                        "text: '" + lang.minusButton + "'," +
                        "preferredSize: [20, 15]" +
                    "}," + //End minusButton
                "}," + //End row1
                "row2: Group {" +
                    "orientation: 'row'," +
                    "margins:0," +
                    "alignment: ['fill','fill']," +
                    "minimumSize: [50, 15]," +
                    "preferredSize: [50, 15]," +
                    "addInMarker: Button {" +
                        "text: '" + COB.CK.markerName.IN + "'," +
                        "alignment: ['fill','fill']" +
                    "}," + //End addInMarker
                    "addOutMarker: Button {" +
                        "text: '" + COB.CK.markerName.OUT + "'," +
                        "alignment: ['fill','fill']" +
                    "}," + //End addOutMarker
                "}," + //End row2
            "}," + //End cueCreationPanel
            "timeModPanel: Panel {" +
                "text: '" + lang.timeModPanelTitle + "'," +
                "margins:15," +
                "alignment: ['fill','fill']," +
                "minimumSize:[180,50]," +
                "orientation: 'column'," +
                "row1: Group {" +
                    "orientation: 'row'," +
                    "margins:0," +
                    "alignment: ['fill','fill']," +
                    "tenBack: Button {" +
                        "text: '" + lang.timeBackTen + "'," +
                        "preferredSize: [20, 15]" +
                    "}," + //End tenBack
                    "oneBack: Button {" +
                        "text: '" + lang.timeBackOne + "'," +
                        "preferredSize: [20, 15]" +
                    "}," + //End oneBack
                    "oneForward: Button {" +
                        "text: '" + lang.timeForwardOne + "'," +
                        "preferredSize: [20, 15]" +
                    "}," + //End oneForward
                    "tenForward: Button {" +
                        "text: '" + lang.timeForwardTen + "'," +
                        "preferredSize: [20, 15]" +
                    "}," + //End tenForward
                "}," + //End row1
            "}," + //End timeModPanel
        "}," + //End row1
        "buttonRow: Group {" +
            "orientation: 'row'," +
            "margins: 20," +
            "alignment: ['fill', 'fill']," +
            "showImportExportButton: Button {" +
                "text: '" + lang.importExportButtonShowText + "'," +
                "alignment: ['left', 'middle']" +
            "}," + //End showImportExportButton
            "b: Button {" +
                "text: '" + lang.closeButton + "'" +
            "}," + //End b
        "}," + //End buttonRow
        "importExport: Panel {" +
            "text: '" + lang.importExportPanelTitle + "'," +
            "margins: 15," +
            "alignment: ['fill','fill']," +
            "visible: true," +
            "row1: Group {" +
                "orientation:'row'," +
                "margins:0," +
                "alignment:['fill','fill']," +
                "timeFormatLabel: StaticText {" +
                    "text: '" + lang.timeFormat + ":'" +
                "}," + //End timeFormatLabel
                "timeFormat: DropDownList {}," +
                "separatorLabel: StaticText {" +
                    "text: '" + lang.infoSeparator + ":'" +
                "}," + //End separatorLabel
                "separator: DropDownList {}" +
            "}," + //End row1
            "row2: Group {" +
                "orientation:'row'," +
                "margins:0," +
                "alignment:['fill','fill']," +
                "importButton: Button {" +
                    "text: '" + lang.importButton + "'," +
                    "alignment: ['fill', 'fill']" +
                "}" + //End importButton
                "exportButton: Button {" +
                    "text: '" + lang.exportButton + "'," +
                    "alignment: ['fill', 'fill']" +
                "}" + //End exportButton
            "}," + //End row2
            "content: EditText {" +
                "properties: {multiline:true}," +
                "alignment: ['fill', 'fill']," +
                "preferredSize: [350,230]" +
            "}," + //End content
        "}," + //End importExport
    "}"; //End group
	myWindow.grp = myWindow.add(res);
//	}catch(e){
//		COB.UI_helper.resError(e, res);
//	}

    //UI shortcut variable declarations
    importExportRow1 = myWindow.grp.importExport.row1;
    importExportRow2 = myWindow.grp.importExport.row2;
    cueCreationPanelRow1 = myWindow.grp.row1.cueCreationPanel.row1;
    cueCreationPanelRow2 = myWindow.grp.row1.cueCreationPanel.row2;
    buttonRow = myWindow.grp.buttonRow;
    setupPanel = myWindow.grp.setupRow.setupPanel;

    timeModPanel = myWindow.grp.row1.timeModPanel;

	//Add the timeFormats
	importExportRow1.timeFormat.add("item", COB.CK.formatTypes.FRAMES);
	importExportRow1.timeFormat.add("item", COB.CK.formatTypes.SECONDS);
	importExportRow1.timeFormat.selection = 0;
	
	//Add the separators
	for (s = 0; s < separators.length; s += 1)
	{
		importExportRow1.separator.add("item", separators[s].getName());
	}

	importExportRow1.separator.selection = 0;
	
    //Event Handlers Set Later

    //The following functions are set later before the window is shown.
    //This allows the global COB.CK object to
	//create functions for use by this UI and set them.

	importExportRow2.exportButton.onClick = null;		//Export function
	cueCreationPanelRow2.addInMarker.onClick = null;	//Set In Cue function
	cueCreationPanelRow2.addOutMarker.onClick = null;	//Set Out Cue function
    moveTime = function () {};

    //UI Specific Event Handlers

	buttonRow.b.onClick = function () {
        myWindow.close();
    };

    setupPanel.mainCompGroup.refreshCompButton.onClick = refreshCompList;

	cueCreationPanelRow1.plusButton.onClick = function () {
		cueCreationPanelRow1.cue.e.text = parseInt(
            cueCreationPanelRow1.cue.e.text, 10) + 1;
	};

	cueCreationPanelRow1.minusButton.onClick = function () {
		cueCreationPanelRow1.cue.e.text = parseInt(
            cueCreationPanelRow1.cue.e.text, 10) - 1;
	};

    timeModPanel.row1.tenBack.onClick = function () {
        moveTime(-10);
    };

    timeModPanel.row1.oneBack.onClick = function () {
        moveTime(-1);
    };

    timeModPanel.row1.oneForward.onClick = function () {
        moveTime(1);
    };

    timeModPanel.row1.tenForward.onClick = function () {
        moveTime(10);
    };
	
	//Have the layout calculate the position of its resources.
	myWindow.layout.layout(true);
	myWindow.onResizing = myWindow.onResize = function () {
        this.layout.resize();
    };
	
    /**
     * The function to run when the refresh button is clicked.
     * 
     * This function starts out as a blank function until it is set by the
     * COB.CK object
     */
    refreshCompList = function () {};
    
	return {
		display: function () {
			if (myWindow !== null &&
                importExportRow2.exportButton.onClick !== null)
			{
				if (myWindow instanceof Window)
				{
					buttonRow.showImportExportButton.notify("onClick");	
					myWindow.center();
					myWindow.show();
				} else {
					myWindow.layout.layout(true);
				}
			}
		},
	
		// GETTERS
		getTimeFormat: function () {
			var f = importExportRow1.timeFormat.selection.text;
			switch (f)
			{
            case COB.CK.formatTypes.FRAMES:
                return COB.CK.formatTypes.FRAMES;
            case COB.CK.formatTypes.SECONDS:
                return COB.CK.formatTypes.SECONDS;
            default:
                COB.alertError(COB.CK.errors.UNKNOWN_FORMAT_TYPE);
                return null;
			}
		},
		getSeparator: function () {
			var s = importExportRow1.separator.selection.text;
			switch (s)
			{
            case 'Tab':
                return "\t";
            case 'Comma':
                return ",";
            case 'New Line':
                return "\n";
            case 'Semi-Colon':
                return ";";
            default:
                alert(COB.CK.errors.UNKNOWN_SEPARATOR_TYPE);
                return null;
			}
		},
		getCueNum: function () {
			return cueCreationPanelRow1.cue.e.text;
		},
		getInfo: function () {
			return myWindow.grp.importExport.content.text;
		},
		// SETTERS
		setInfo: function (t)
		{
			myWindow.grp.importExport.content.text = t;
		},
		//Sets the onClick handler for the "Export" button
		setExportHandler: function (f)
		{
			importExportRow2.exportButton.onClick = f;
		},
		//Sets the onClick handler for the "Import" button
		setImportHandler: function (f)
		{
			importExportRow2.importButton.onClick = f;
		},
		//Sets the onClick handler for the 'Add In cue' button
		setAddInCueHandler: function (f)
		{
			cueCreationPanelRow2.addInMarker.onClick = f;
		},
		//Sets the onClick handler for the 'Add Out cue' button
		setAddOutCueHandler: function (f)
		{
			cueCreationPanelRow2.addOutMarker.onClick = f;
		},
        /**
         * Sets the function to be called when the refresh main comp list
         * button is clicked.
         * @param {Function} f The function to be called when the refresh main
         * comp list button is clicked.
         */
        setRefreshCompListHandler: function (f)
        {
            refreshCompList = f;
        },
        /**
         * Updates the list of compositions within the "Main Composition"
         * drop down list.
         *
         * This should be run once upon showing the UI and every time the
         * refresh button is clicked.
         * @param {Array} l An array of items to be placed within the
         * "Main Comp" list.
         */
        setMainCompList: function (l)
        {
            var list = setupPanel.mainCompGroup.e, i;
            for (i = 0; i < l.length; i += 1)
            {
                list.add("item", l[i]);
            }
        },
        /**
         *Sets the function that handles the movement of the current time
         *indicator when any of the time modification buttons are clicked.
         *
         *@param {Function} f The function to run when any of the time
         *modification buttons are clicked.The function should have one
         *parameter that accepts an integer representing how many frames the
         *current time indicator should move. Negative numbers should move the
         *time indicator back in time, positive numbers should move the time
         *indicator forward in time.
         */
        setMoveTimeHandler: function (f) {
            moveTime = f;
        }
	};
}());

/******************************************************************\
>>>>>>> COB.CK FUNCTIONS
\******************************************************************/

//Go through a preflight error check
COB.CK.noBasicErrors = function ()
{
	//Check for errors
	if (app.project === null || app.project === undefined)
	{
		COB.CK.alertError(COB.CK.errors.UNDEFINED_PROJECT);
		return false;
	} else if (COB.CK.currentComp === null ||
        COB.CK.currentComp === undefined) {
		COB.CK.alertError(COB.CK.errors.UNDEFINED_COMP);
		return false;
	} else if (COB.CK.UI.getTimeFormat() === COB.CK.formatTypes.SECONDS &&
        COB.CK.UI.getSeparator() === "Semi-Colon") {
		COB.CK.alertError(COB.CK.errors.SECONDS_WITH_SEMI_COLON);
	} else {
		return true;
	}
};

/**
 * Gathers an array of compositions that are within the project and updates
 * the composition list within the UI.
 * @return {Array|Bool} If there were no errors, an array of compositions is
 * returned. Otherwise, false is returned.
 */
COB.CK.setCompList = function ()
{
    var comps;
    if (COB.CK.noBasicErrors())
    {
        comps = COB.PROJ_helper.getCompList();
        COB.CK.UI.setMainCompList(comps);
    } else {
        COB.alertError("Main comp list could not be set.", true);
    }
};

COB.CK.getMarkerNullReference = function ()
{
	//A reference to the marker null within the composition
	var markerNull = {};
	
	if (COB.CK.currentComp !== null && COB.CK.currentComp !== undefined)
	{
		//See if the current composition has a PIL marker layer
		if (!COB.CK.markerLayerExists())
		{
			app.beginUndoGroup("Add " + COB.CK.markerLayerName + " layer");
			//Create the marker null
			markerNull = COB.CK.currentComp.layers.addNull();
			markerNull.name = COB.CK.markerLayerName;
			app.endUndoGroup();
			return markerNull;
		} else {
			return COB.CK.currentComp.layers.byName(COB.CK.markerLayerName);
		}
	} else {
		COB.alertError(COB.CK.errors.UNDEFINED_COMP);
		return false;
	}
};

COB.CK.getCurrentCompTime = function ()
{
	return COB.CK.getMarkerNullReference().time;
};

COB.CK.markerLayerExists = function ()
{
	try {
		if (COB.CK.currentComp.layers.byName(COB.CK.markerLayerName) === null)
		{
			return false;
		} else {
			return true;
		}
	} catch (e) {
		alert(e);
		return false;
	}
};

COB.CK.exportData = function ()
{
    COB.LOG.debug("Exporting Timecodes");
    //Variable declarations
    var markerNull,
    separator,
    format,
    info,
    nl,
    markerRef, //Reference to the marker property of the marker null layer
    currMarkerCueNum, //The cue number at the current marker within the loop
    currMarkerCueType, //The cue type at the current marker within the loop
    currMarkerComment,
    prevMarkerCueNum, //The cue number at the previous marker within the loop
    prevMarkerCueType, //The cue type at the previous marker within the loop
    wellFormed,
    usersTimecodeType,
    i;

	//Get the current composition and selected layers
	COB.CK.currentComp = COB.PROJ_helper.getActiveComp();
    COB.LOG.debug("currentComp.name: " + COB.CK.currentComp.name);
	markerNull = COB.CK.getMarkerNullReference();
    COB.LOG.debug("markerNull.name: " + markerNull.name);
	separator = COB.CK.UI.getSeparator();
    COB.LOG.debug("separator: " + separator);
	format = COB.CK.UI.getTimeFormat();
    COB.LOG.debug("format: " + format);

	if (format !== null &&
        separator !== null &&
        COB.CK.noBasicErrors() &&
        COB.CK.markerLayerExists() &&
        markerNull.property("Marker").numKeys !== 0)
	{
		info = "";
		nl = "\n";
		markerRef = null;
		currMarkerCueNum = null; 
		currMarkerCueType = null;
		prevMarkerCueNum = null;
		prevMarkerCueType = null;
		
		wellFormed = true;

		//Get the user's timecode display type so we can change it back when
        //we're done.
		usersTimecodeType = app.project.timecodeDisplayType;
		
		//Set the timecode display type to the currently selected timecode
        //display type in the UI.
		if (format === COB.CK.formatTypes.FRAMES) {
            COB.LOG.debug("Setting timecodeDisplayType to frames");
			app.project.timecodeDisplayType = TimecodeDisplayType.FRAMES;
		} else if (format === COB.CK.formatTypes.SECONDS) {
			COB.LOG.debug("Setting timecodeDisplayType to time");
            app.project.timecodeDisplayType = TimecodeDisplayType.TIMECODE;
		}

        COB.LOG.debug("Adding header rows");
		//Setup header rows for information
		info += "Cue";
        info += separator;
		info += "In Point";
        info += separator;
		info += "Out Point";
        info += separator;
		info += nl;

        COB.LOG.debug("Looping through the markers: ");
		for (i = 1; i <= markerNull.property("Marker").numKeys; i += 1)
		{
            COB.LOG.separate([0,1]);
			markerRef = markerNull.property("Marker");

			//Grab the information
			currMarkerComment = markerRef.keyValue(i).comment;
            COB.LOG.debug("currMarkerComment: " + currMarkerComment);
			currMarkerCueNum = COB.CK.regex.getCueNumber.exec(
                currMarkerComment).toString();
            COB.LOG.debug("currMarkerCueNum: " + currMarkerCueNum);
			currMarkerCueType = COB.CK.regex.getCueType.exec(
                currMarkerComment).toString();
			COB.LOG.debug("currMarkerCueType: " + currMarkerCueType);

            //Is this the first enumeration?
			if (prevMarkerCueNum !== null)
			{//No, do error checking
				if (prevMarkerCueType === COB.CK.markerName.OUT &&
                    currMarkerCueType !== COB.CK.markerName.IN)
				{
					//This marker SHOULD HAVE been an in marker for the markers
                    //to be well-formed. Do not continue.
					wellFormed = false;
					break;
				} else if (prevMarkerCueType === COB.CK.markerName.IN &&
                    currMarkerCueType !== COB.CK.markerName.OUT) {
					//This marker SHOULD HAVE been an out marker for the markers
                    // to be well-formed. Do not continue.
					wellFormed = false;
					break;
				}
			}
			
			//If this is an IN marker, insert the cue number
			if (currMarkerCueType === COB.CK.markerName.IN)
			{
                COB.LOG.debug("IN marker!");
				info += currMarkerCueNum;
				info += separator;
			} else {
                COB.LOG.debug("OUT marker!");
            }
			
			//Add the cue time
			info += COB.LAYER_helper.getMarkerTime(markerNull,
                COB.LAYER_helper.findMarkerIndex(
                    markerNull,
                    currMarkerComment
                ));
			
			//If this marker is an OUT marker, add a new line
			if (currMarkerCueType === COB.CK.markerName.OUT)
			{
				info += nl;
			} else {//Otherwise, add a separator
				info += separator;
			}

			//Store the information within the cue for error checking in the
            //next enumeration
			prevMarkerCueNum = currMarkerCueNum;
			prevMarkerCueType = currMarkerCueType;
		}
		
		if (wellFormed)
		{
			COB.CK.UI.setInfo(info);
		} else {
			COB.alertError(COB.CK.errors.MALFORMED_MARKERS);
		}
		
		//Reset the timecode display type to the user's preference	
		app.project.timecodeDisplayType = usersTimecodeType;
	}
};

//Validates the import text from the user
COB.CK.validateImport = function (info)
{
	//Implement!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	return true;
};

COB.CK.importData = function () {
    //Variable declarations
    var markerNull,
        cues,
        cue,
        l,
        c,
        usersTimecodeType,
        info,
        lines,
        col,
        currCue,
        currIn,
        currOut,
        separator,
        format;
	//Get the current composition and selected layers
	COB.CK.currentComp = COB.PROJ_helper.getActiveComp();
	markerNull = COB.CK.getMarkerNullReference();
    separator = COB.CK.UI.getSeparator();
	cues = [];

    //Cue object
	cue = function (num, inPoint, outPoint) {
        //Variable declarations
        var myNum = num,
            myInPoint = inPoint,
            myOutPoint = outPoint;
		
		return {
			getNum: function () {
				return myNum;
			},
			getInPoint: function () {
				return myInPoint;
			},
			getOutPoint: function () {
				return myOutPoint;
			},
			setInPoint: function (i) {
				myInPoint = i;
			},
			setOutPoint: function (o) {
				myOutPoint = o;
			},
			toString: function () {
				return "Cue: " + myNum + "; InPoint: " + myInPoint +
                    "; OutPoint: " + myOutPoint + ";";
			}
		};
	}; 
	
	if (COB.CK.noBasicErrors())
	{
        //Get the currently selected timecode format from the UI
        format = COB.CK.UI.getTimeFormat();

		//Get the user's timecode display type so we can change it to
		//frames for calculations and then change it back when we're done.
		usersTimecodeType = app.project.timecodeDisplayType;
		
		//Set the timecode display type to the currently selected timecode
        //display type in the UI.
		if (format === COB.CK.formatTypes.FRAMES) {
			app.project.timecodeDisplayType = TimecodeDisplayType.FRAMES;
		} else if (format === COB.CK.formatTypes.SECONDS) {
			app.project.timecodeDisplayType = TimecodeDisplayType.TIMECODE;
		}
		
		//Get the current data from the UI
		info = COB.CK.UI.getInfo();
		if (COB.CK.validateImport(info))
		{
			//Split up the data
			lines = info.split("\n");
			//Go through each line
			for (l = 0; l < lines.length; l += 1)
			{
				col = lines[l].split(separator);
				cues[cues.length] = cue(col[0], col[1], col[2]);
			}
		
			//Go create each of the cues
			markerNull = COB.CK.getMarkerNullReference();

            COB.LOG.separate();

			for (c = 0; c < cues.length; c += 1)
			{
				currCue = cues[c];
                COB.LOG.debug(currCue.toString());

                //Get the current "in" time based upon the selected time format
                currIn =currentFormatToTime(currCue.getInPoint(),
                        COB.CK.currentComp.frameRate);

                //Add inPoint Marker
				COB.LAYER_helper.addMarker(markerNull, currIn,
                    "" + currCue.getNum() + " " + COB.CK.markerName.IN
                );
                
                //Get the current "out" time based upon the selected time format
                currOut = currentFormatToTime(currCue.getOutPoint(),
                        COB.CK.currentComp.frameRate);

				//Add outPoint Marker
				COB.LAYER_helper.addMarker(markerNull, currOut,
                    "" + currCue.getNum() + " " + COB.CK.markerName.OUT);
			}
		}
		
		//Reset the timecode display type to the user's preference	
		app.project.timecodeDisplayType = usersTimecodeType;
	}
};

//Adds a cue to the Cue Keeper null
COB.CK.addCue = function (type, cueNum)
{
    //Variable declarations
    var currentCompTime,
        markerText,
        markerNullRef,
        previousMarker;


	//Make sure the current composition is defined:
	COB.CK.currentComp = COB.PROJ_helper.getActiveComp();
	
	//Get the current Comp Time
	currentCompTime = COB.CK.getCurrentCompTime();
	
	//Set the text to be placed in the marker
	markerText = cueNum + " " + type;
	
	//Get the marker null reference
	markerNullRef = COB.CK.getMarkerNullReference();
	
	//Retrieve the index of a marker that already exists (or false)
	previousMarker = COB.LAYER_helper.findMarkerIndex(markerNullRef,
        markerText);
	
	//Make sure a marker for this cue number doesn't already exist
	if (previousMarker === false)
	{
		COB.LAYER_helper.addMarker(markerNullRef, currentCompTime, markerText);
	} else {
		//This marker already exists. Confirm with the user to see if the marker
        // should be moved.
		if (confirm(COB.CK.confirmMarkerMove))
		{
			//Delete the old marker
			COB.LAYER_helper.deleteMarker(markerNullRef, previousMarker);
			
			//Add the marker
			COB.LAYER_helper.addMarker(markerNullRef,
                currentCompTime,
                markerText
            );
		}
	}
};

/**
 *Moves the current time indicator n frames. A negative number will move the
 *current time indicator backwards, a positive number will move it forward.
 *
 *@param {Int} n The number of frames to move the current time indicator
 *backwards or forwards.
 */
COB.CK.moveTime = function (n) {
    if(COB.CK.noBasicErrors())
    {
        COB.CK.currentComp = COB.PROJ_helper.getActiveComp();

        //Transform the amount of frames to move to
        //the amount of seconds to move
        n = currentFormatToTime(n, COB.CK.currentComp.frameRate);
        
        COB.CK.currentComp.time += n;
    }
};

/******************************************************************\
>>>>>>> COB.CK MAIN
\******************************************************************/

//Setup UI event handlers

COB.CK.UI.setRefreshCompListHandler(COB.CK.setCompList());

//Export handler
COB.CK.UI.setExportHandler(COB.CK.exportData);

//Import handler
COB.CK.UI.setImportHandler(COB.CK.importData);

//Add In Cue handler
COB.CK.UI.setAddInCueHandler(function () {
	COB.CK.addCue(COB.CK.markerName.IN, COB.CK.UI.getCueNum());
});

//Add Out Cue handler
COB.CK.UI.setAddOutCueHandler(function () {
	COB.CK.addCue(COB.CK.markerName.OUT, COB.CK.UI.getCueNum());
});

//Add the time modification handler
COB.CK.UI.setMoveTimeHandler(COB.CK.moveTime);


//Display the UI
COB.CK.UI.display();
